package com.inoneone.youba.mcht.controller;

import com.inoneone.toolkit.enums.*;
import com.inoneone.toolkit.exception.AssertUtil;
import com.inoneone.toolkit.exception.BusinessRuntimeException;
import com.inoneone.toolkit.exception.RegExp;
import com.inoneone.youba.mcht.dao.po.Card;
import com.inoneone.youba.mcht.dao.po.Merchant;
import com.inoneone.youba.mcht.dto.BaseRsp;
import com.inoneone.youba.mcht.dto.PageRsp;
import com.inoneone.youba.mcht.dto.req.*;
import com.inoneone.youba.mcht.dto.rsp.CardFlowRsp;
import com.inoneone.youba.mcht.dto.rsp.MyCardsRsp;
import com.inoneone.youba.mcht.enums.Constants;
import com.inoneone.youba.mcht.enums.ErrorCode;
import com.inoneone.youba.mcht.pojo.Event;
import com.inoneone.youba.mcht.service.CardApi;
import com.inoneone.youba.mcht.service.MerchantApi;
import com.inoneone.youba.mcht.service.SafeApi;
import com.inoneone.youba.mcht.util.CommonUtil;
import com.inoneone.youba.mcht.util.DateUtil;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.OutputStream;
import java.util.*;


@RestController
@RequestMapping(value = "/card", method = {RequestMethod.POST})
public class CardController {
    @Autowired
    private CardApi cardApi;

    @Autowired
    SafeApi safeApi;

    @Autowired
    MerchantApi merchantApi;

    /**
     * Description: 我的ic卡列表信息</br>
     * Date: 2017-07-04 10:58:57</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/myCards")
    @ResponseBody
    public Object myCards(HttpSession httpSession, @RequestBody MyCardsReq myCardsReq) {
        //参数检查
        AssertUtil.isBetween(myCardsReq.getQueryType(), 1, 4, ErrorCode.CARD_QUERY_TYPE);
        myCardsReq.validate();

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //查询ic卡
        PageRsp<MyCardsRsp> pageInfo = cardApi.queryCard(myCardsReq, merchant.getId());

        //返回
        return new BaseRsp(pageInfo);
    }

    @PostMapping(value = "/myCardsPlus")
    @ResponseBody
    public Object myCardsPlus(HttpSession httpSession, @RequestBody MyCardsPlusReq myCardsPlusReq) {
        //参数检查
//        myCardsPlusReq.validate();
        AssertUtil.isBetween(myCardsPlusReq.getPageNum(), 1, Integer.MAX_VALUE, ErrorCode.PAGE_NO);
        AssertUtil.isBetween(myCardsPlusReq.getPageSize(), 1, 1000, ErrorCode.PAGE_SIZE);

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //查询ic卡
        PageRsp<MyCardsRsp> pageInfo = cardApi.queryCardPlus(myCardsPlusReq.getKeywords(), merchant.getId(), myCardsPlusReq.getPageNum(), myCardsPlusReq.getPageSize());

        //返回
        return new BaseRsp(pageInfo);
    }

    /**
     * Description: 我的ic卡资金流水信息</br>
     * Date: 2017-07-04 10:58:57</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/cardFlow")
    @ResponseBody
    public Object cardFlow(HttpSession httpSession, @RequestBody CardFlowReq cardFlowReq) {
        //参数检查
        if (!CommonUtil.isNullOrEmpty(cardFlowReq.getCardId())) {
            AssertUtil.isMatch(cardFlowReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        }
        AssertUtil.isBetween(cardFlowReq.getPageNum(), 1, Integer.MAX_VALUE, ErrorCode.PAGE_NO);
        AssertUtil.isBetween(cardFlowReq.getPageSize(), 1, Integer.MAX_VALUE, ErrorCode.PAGE_SIZE);

        if (cardFlowReq.getBeginTime() != null) {
            AssertUtil.isBetween(cardFlowReq.getBeginTime(), Constants.DATETIME_BEGIN, Constants.DATETIME_END, ErrorCode.DATE_TIME);

        }
        if (cardFlowReq.getEndTime() != null) {
            AssertUtil.isBetween(cardFlowReq.getEndTime(), Constants.DATETIME_BEGIN, Constants.DATETIME_END, ErrorCode.DATE_TIME);
        }
        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //查询ic卡
        PageRsp<CardFlowRsp> pageInfo = cardApi.cardFlow(cardFlowReq, merchant.getId());

        //返回
        return new BaseRsp(pageInfo);
    }

    /**
     * Description: 流水导出excel</br>
     * Date: 2017-08-27 23:24:33</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "cardFlowExcel")
    public void cardFlowExcel(HttpSession httpSession, HttpServletResponse response, CardFlowReq cardFlowReq) throws Exception {

        BaseRsp baseRsp = (BaseRsp) cardFlow(httpSession, cardFlowReq);

        // 1、创建工作簿(WritableWorkbook)对象，打开excel文件，若文件不存在，则创建文件
        OutputStream outputStream = response.getOutputStream();
        response.setHeader("Content-disposition", "attachment; filename=" + new String("ic卡资金流水".getBytes("utf-8"), "8859_1") + ".xls");// 设定输出文件头
        response.setContentType("application/msexcel");// 定义输出类型
        WritableWorkbook writeBook = Workbook.createWorkbook(outputStream);

        // 2、新建工作表(sheet)对象，并声明其属于第几页
        WritableSheet firstSheet = writeBook.createSheet("ic卡资金流水", 0);// 第一个参数为工作簿的名称，第二个参数为页数

        // 3、创建单元格(Label)对象，
        //表头
        firstSheet.addCell(new Label(0, 0, "ic卡号"));
        firstSheet.addCell(new Label(1, 0, "用户姓名"));
        firstSheet.addCell(new Label(2, 0, "消费类型"));
        firstSheet.addCell(new Label(3, 0, "增加金额"));
        firstSheet.addCell(new Label(4, 0, "减少金额"));
        firstSheet.addCell(new Label(5, 0, "当前余额"));
        firstSheet.addCell(new Label(6, 0, "交易时间"));

        PageRsp<CardFlowRsp> cardFlowRspList = (PageRsp<CardFlowRsp>) baseRsp.getContent();
        List<CardFlowRsp> resultList = cardFlowRspList.getResultList();
        int size = cardFlowRspList.getResultList().size();
        for (int i = 0; i < size; ++i) {
            firstSheet.addCell(new Label(0, i + 1, resultList.get(i).getCardId()));
            firstSheet.addCell(new Label(1, i + 1, resultList.get(i).getUserName()));
            if (resultList.get(i).getSubject() == Subject.PAY.getCode()) {
                firstSheet.addCell(new Label(2, i + 1, Subject.PAY.getDesc()));

            } else {
                firstSheet.addCell(new Label(2, i + 1, Subject.CHARGE.getDesc()));

            }
            if (resultList.get(i).getChangeType() == ChangeType.ADD.getCode()) {
                firstSheet.addCell(new Label(3, i + 1, resultList.get(i).getChangeAmount().toString()));
            } else {
                firstSheet.addCell(new Label(4, i + 1, resultList.get(i).getChangeAmount().toString()));

            }
            firstSheet.addCell(new Label(5, i + 1, resultList.get(i).getBalance().toString()));
            firstSheet.addCell(new Label(6, i + 1, resultList.get(i).getCreateTime() == null ? "" : DateUtil.formatDate(resultList.get(i).getCreateTime())));

        }

        // 4、打开流，开始写文件
        writeBook.write();

        // 5、关闭流
        writeBook.close();
        outputStream.flush();
        outputStream.close();
    }

    @PostMapping(value = "/cardFlowPlus")
    @ResponseBody
    public Object cardFlowPlus(HttpSession httpSession, @RequestBody CardFlowPlusReq cardFlowPlusReq) {
        CardFlowReq cardFlowReq = new CardFlowReq();
        if (!CommonUtil.isNullOrEmpty(cardFlowPlusReq.getMonth())) {
            AssertUtil.isMatch(cardFlowPlusReq.getMonth(), RegExp.YYYYMM, ErrorCode.DATE);

            //年月
            Date month = DateUtil.parseDate(cardFlowPlusReq.getMonth(), "yyyy-MM");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(month);
            calendar.set(Calendar.DAY_OF_MONTH, 1);

            //开始时间
            cardFlowReq.setBeginTime(calendar.getTime().getTime());

            //结束时间
            calendar.roll(Calendar.DAY_OF_MONTH, -1);
            cardFlowReq.setEndTime(calendar.getTime().getTime());

        }
        BeanUtils.copyProperties(cardFlowPlusReq, cardFlowReq);

        //返回
        return cardFlow(httpSession, cardFlowReq);
    }

    /**
     * Description:ic卡充值</br>
     * Date: 2017-07-04 11:00:05</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/recharge")
    @ResponseBody
    public Object recharge(HttpSession httpSession, @RequestBody RechargeReq rechargeReq) {

        //参数检查
        AssertUtil.isMatch(rechargeReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.isMatch(rechargeReq.getAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        AssertUtil.hasText(rechargeReq.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);


        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!rechargeReq.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //校验ic卡是否存在
        Card card = cardApi.queryCard(rechargeReq.getCardId(), merchant.getId());

        //充值
        cardApi.recharge(rechargeReq, merchant.getId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("ic卡[" + rechargeReq.getCardId() + "]执行了充值操作");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(rechargeReq.getCardId());
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/freeze")
    @ResponseBody
    public Object freeze(HttpSession httpSession, @RequestBody FreezeReq freezeReq) {

        //参数检查
        AssertUtil.isMatch(freezeReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.hasText(freezeReq.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);

        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!freezeReq.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //校验ic卡是否存在
        Card card = cardApi.queryCard(freezeReq.getCardId(), merchant.getId());

        //冻结
        cardApi.freeze(freezeReq, CardStatus.FREEZEN.getCode(), merchant.getId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("ic卡[" + freezeReq.getCardId() + "]执行了冻结操作");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(freezeReq.getCardId());
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/unfreeze")
    @ResponseBody
    public Object unfreeze(HttpSession httpSession, @RequestBody FreezeReq freezeReq) {

        //参数检查
        AssertUtil.isMatch(freezeReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.hasText(freezeReq.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);

        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!freezeReq.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //校验ic卡是否存在
        Card card = cardApi.queryCard(freezeReq.getCardId(), merchant.getId());

        //解冻
        cardApi.freeze(freezeReq, CardStatus.NOMAL.getCode(), merchant.getId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("ic卡[" + freezeReq.getCardId() + "]执行了解冻操作");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(freezeReq.getCardId());
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    /**
     * Description: ic卡扣款</br>
     * Date: 2017-07-04 11:19:27</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/reduce")
    @ResponseBody
    public Object reduce(HttpSession httpSession, @RequestBody RechargeReq rechargeReq) {

        //参数检查
        AssertUtil.isMatch(rechargeReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.isMatch(rechargeReq.getAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        AssertUtil.hasText(rechargeReq.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);

        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!rechargeReq.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //校验ic卡是否存在
        Card card = cardApi.queryCard(rechargeReq.getCardId(), merchant.getId());

        //扣款
        cardApi.reduce(rechargeReq, merchant.getId(), false);

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("ic卡[" + rechargeReq.getCardId() + "]执行了扣款操作");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(rechargeReq.getCardId());
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    @PostMapping(value = "/editCard")
    @ResponseBody
    public Object editCard(HttpSession httpSession, @RequestBody EditCardReq editCardReq) {

        //参数检查
        if (editCardReq.getCardId() != null) {
            AssertUtil.isMatch(editCardReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);

        }
        if (editCardReq.getUserName() != null) {
            AssertUtil.isMatch(editCardReq.getUserName(), RegExp.REAL_NAME, ErrorCode.USER_NAME);

        }
        if (editCardReq.getMobile() != null) {
            AssertUtil.isMatch(editCardReq.getMobile(), RegExp.MOBILE, ErrorCode.MOBILE);

        }

        //获取session
        Merchant merchant = CommonUtil.getSession(httpSession);

        //校验ic卡是否存在
        cardApi.queryCard(editCardReq.getCardId(), merchant.getId());

        //修改ic卡信息
        cardApi.editCard(editCardReq, merchant.getId());

        //返回
        return new BaseRsp();
    }

    /**
     * Description: 批量充值，相同金额</br>
     * Date: 2017-06-28 10:12:30</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/batchRecharge")
    @ResponseBody
    public Object batchRecharge(HttpSession httpSession, @RequestBody BatchRechargeReq batchRechargeReq) {

        //参数检查
        AssertUtil.isMatch(batchRechargeReq.getAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        AssertUtil.hasText(batchRechargeReq.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);
        AssertUtil.notNull(batchRechargeReq.getCards(), ErrorCode.BATCH_RECHARGE_CARDS);

        if (batchRechargeReq.getCards().isEmpty()) {
            throw new BusinessRuntimeException(ErrorCode.BATCH_RECHARGE_CARDS);
        }

        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!batchRechargeReq.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //去重
        batchRechargeReq.setCards(new ArrayList<>(new HashSet<>(batchRechargeReq.getCards())));

        //校验ic卡是否存在
        cardApi.checkBatchCards(batchRechargeReq.getCards(), merchant.getId());

        //获取第一张卡
        Card card = cardApi.queryCard(batchRechargeReq.getCards().get(0), merchant.getId());

        //批量充值
        cardApi.batchRecharge(batchRechargeReq, merchant.getId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("卡号[" + batchRechargeReq.getCards().get(0) + "]等ic卡执行了批量充值操作，充值金额" + batchRechargeReq.getAmount() + "元");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(batchRechargeReq.getCards().get(0));
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }

    /**
     * Description: 批量充值，不同金额</br>
     * Date: 2017-06-28 10:12:30</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @PostMapping(value = "/batchRecharge2")
    @ResponseBody
    public Object batchRecharge2(HttpSession httpSession, @RequestBody BatchRecharge2Req batchRecharge2Req) {

        //参数检查
        AssertUtil.hasText(batchRecharge2Req.getPayPassword(), 32, ErrorCode.PASSWORD_BAD);
        AssertUtil.notNull(batchRecharge2Req.getCards(), ErrorCode.BATCH_RECHARGE_CARDS);

        if (batchRecharge2Req.getCards().isEmpty()) {
            throw new BusinessRuntimeException(ErrorCode.BATCH_RECHARGE_CARDS);
        }

        //ic卡参数检查
        for (BatchRecharge2Req.CardsBean cardsBean : batchRecharge2Req.getCards()) {
            AssertUtil.isMatch(cardsBean.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
            AssertUtil.isMatch(cardsBean.getAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        }

        //检验支付密码
        Merchant merchant = CommonUtil.getSession(httpSession);
        if (!batchRecharge2Req.getPayPassword().equals(merchant.getPayPassword())) {
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_WRONG);
        }

        //重复参数判断
        HashSet<String> noDupSet = new HashSet<>();
        for (BatchRecharge2Req.CardsBean card : batchRecharge2Req.getCards()) {
            if (!noDupSet.add(card.getCardId())) {
                throw new BusinessRuntimeException(ErrorCode.BATCH_RECHARGE_DUP_CARD);

            }
        }

        //校验ic卡是否存在
        cardApi.checkBatchCards(new ArrayList<>(noDupSet), merchant.getId());

        //获取第一张卡
        Card card = cardApi.queryCard(batchRecharge2Req.getCards().get(0).getCardId(), merchant.getId());

        //充值
        cardApi.batchRecharge2(batchRecharge2Req, merchant.getId());

        //记录日志
        Event event = new Event();
        event.setType(EventType.CARD.getCode());
        event.setDesc("卡号[" + batchRecharge2Req.getCards().get(0).getCardId() + "]等ic卡执行了批量充值操作");
        event.setMchId(merchant.getId());
        event.setMchName(merchant.getMchName());
        event.setCardId(batchRecharge2Req.getCards().get(0).getCardId());
        event.setCardName(card.getUserName());
        safeApi.log(event);

        //返回
        return new BaseRsp();
    }
}
